package com.ccc.dingtalk.listener;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.ccc.dingtalk.config.DingtalkProperties;
import com.ccc.dingtalk.pojo.vo.UserAttendanceVO;
import com.ccc.dingtalk.service.dingtalk.AttendanceService;
import com.dingtalk.open.app.api.GenericEventListener;
import com.dingtalk.open.app.api.OpenDingTalkStreamClientBuilder;
import com.dingtalk.open.app.api.message.GenericOpenDingTalkEvent;
import com.dingtalk.open.app.api.security.AuthClientCredential;
import com.dingtalk.open.app.stream.protocol.event.EventAckStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * 钉钉Stream监听器
 *
 * @author superC
 * @version 1.0.0
 * @date 2023-08-10
 */

@Component
public class DingtalkStreamListener {
    protected static final Logger logger = LoggerFactory.getLogger(DingtalkStreamListener.class);

    @Autowired
    private DingtalkProperties dingtalkProperties;

    @Autowired
    private AttendanceService attendanceService;

    /**
     * 订阅钉钉Stream推送
     */
    @PostConstruct
    public void startStreamListener() {
        try {
            OpenDingTalkStreamClientBuilder
                    .custom()
                    .credential(new AuthClientCredential(dingtalkProperties.getAppKey(), dingtalkProperties.getAppSecret()))
                    //注册事件监听
                    .registerAllEventListener(new GenericEventListener() {
                        public EventAckStatus onEvent(GenericOpenDingTalkEvent event) {
                            try {
                                //处理事件
                                process(event);
                                //消费成功
                                return EventAckStatus.SUCCESS;
                            } catch (Exception e) {
                                //消费失败
                                return EventAckStatus.LATER;
                            }
                        }
                    })
                    .build().start();
        } catch (Exception e) {
            logger.error("【钉钉Stream】-> 【捕获异常-注册钉钉Stream监听】\r\n异常记录：", e);
        }
    }

    /**
     * 处理钉钉事件返回内容
     *
     * @param event
     */
    private void process(GenericOpenDingTalkEvent event) {
        //事件唯一Id
        String eventId = event.getEventId();
        //事件类型
        String eventType = event.getEventType();
        //事件产生时间
        Long bornTime = event.getEventBornTime();
        //获取事件体
        JSONObject bizData = event.getData();
        if (bornTime != null) {
            logger.info("事件类型：" + eventType + "，事件产生时间：" + DateUtil.date(bornTime).toString());
        }
//        logger.info(bizData.toString());

        reGetList2SendWs2();
    }

    /**
     * 重新获取数据并向WS发送
     */
    private void reGetList2SendWs2() {
        try {
            // 重新获取考勤列表数据
            List<UserAttendanceVO> resultList = attendanceService.getTodayAttendanceList2AllUser();
            logger.info("【钉钉Stream】-> 订阅钉钉推送——考勤打卡事件，重新获取数据，共获取到{}条", resultList.size());
            if (resultList.isEmpty()) {
                logger.info("【钉钉Stream】-> 重新获取数据，没有查询到数据，通过WS向前端发送空数组！");
                // 再通过ws，向前端发送数据
                WebSocket.sendObjectInfo(ListUtil.empty());
            } else {
                // 再通过ws，向前端发送数据
                WebSocket.sendObjectInfo(resultList);
            }
            logger.info("【钉钉Stream】-> 重新获取的数据已通过WS向前端发送！");
        } catch (Exception e) {
            logger.error("【钉钉Stream】-> 【捕获异常-重新获取数据】\r\n异常记录：", e);
        }
    }

}
